package com.toe.common.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.coremedia.iso.IsoFile;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.net.URLEncoder;

public class FileUtils {

    /**
     * 上传文件的方法
     * @param pathDir 上传文件的目录路径
     * @param file 上传的文件
     * @return 返回文件名
     */
    public static String upload(String pathDir, MultipartFile file)
            throws IOException {
        System.out.println("=============进入上传文件的方法=============");
        // 获取保存文件的相对路径
        String originalFilename = file.getOriginalFilename();
        String type = FileUtil.extName(originalFilename);
        File fileDir = new File(pathDir);
        if (!fileDir.exists()){
            fileDir.mkdirs();
        }

        // 文件唯一标识
        String uuid = IdUtil.fastSimpleUUID();
        String fileName =  uuid + StrUtil.DOT + type;
        String filePath = pathDir + StrUtil.SLASH+ fileName;
        System.out.println("=====文件: "+pathDir);
        File saveFile = new File(filePath);

        // 保存文件
        System.out.println("=============开始保存文件=============");
        file.transferTo(saveFile);
        System.out.println("保存成功");
        return fileName;

    }

    /**
     * 下载文件的方法
     * @param filePath 文件地址
     * @param fileName 下载后文件的名字
     */
    public static void download(String fileName, String filePath, HttpServletResponse response)
            throws IOException {
        File uploadFile = new File(filePath);
        String type = FileUtil.extName(uploadFile);
        String uploadFileName = fileName + StrUtil.DOT + type;
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename="
                + URLEncoder.encode(uploadFileName, "utf-8"));
        response.setContentType("application/octet-stream");

        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    /**
     * 截取视频的一帧图片作为封面
     * @param videoPath 视频的地址
     * @param dirPath 封面图片的保存目录
     * @return 返回文件名
     */
    public static String fetchFrame(String videoPath, String dirPath)
            throws IOException {
        System.out.println("开始保存图片");
        File fileDir = new File(dirPath);
        if (!fileDir.exists()){
            fileDir.mkdirs();
        }

        System.out.println("保存图片的类型");
        String type = "jpg";
        String fileId = IdUtil.fastSimpleUUID();
        String fileName = fileId+StrUtil.DOT + type;
        String filePath = dirPath + StrUtil.SLASH + fileName;
        File targetFile = new File(filePath);
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoPath);
        ff.start();
        int length = ff.getLengthInFrames();
        int i = 0;
        Frame f = null;
        while (i < length) {
            // 去掉前500帧，避免出现全黑的图片，依自己情况而定
            f = ff.grabImage();
            if ((i > 500) && (f.image != null)) {
                break;
            }
            i++;
        }
        ImageIO.write(FrameToBufferedImage(f), "jpg", targetFile);
        //ff.flush();
        ff.stop();
        System.out.println("生成缩略图完成");
        return fileName;
    }

    /**
     * 截图图片
     * @param frame
     * @return
     */
    private static BufferedImage FrameToBufferedImage(Frame frame) {
        //创建BufferedImage对象
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bufferedImage = converter.getBufferedImage(frame);
        return bufferedImage;
    }

    /**
     * 将MultipartFile转化为File类的方法
     * @param multipartFile
     * @return
     * @throws IOException
     */
    public static File multipartFileToFile(MultipartFile multipartFile) {
        File toFile = null;
        if (!multipartFile.equals("") && !(multipartFile.getSize() <= 0)) {
            try(InputStream ins = multipartFile.getInputStream()) {
                toFile = new File(multipartFile.getOriginalFilename());
                inputStreamToFile(ins, toFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return toFile;
    }

    /**
     * 将File转化为MultipartFile类的方法
     * @param file
     * @return
     */
    public static MultipartFile fileToMultipartFile(File file) {
        FileItem fileItem = getMultipartFile(file,"tempFileItem");
        return new CommonsMultipartFile(fileItem);
    }

    private static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void deleteTempFile(File file){
        if(file!=null){
            File delFile = new File(file.toURI());
            delFile.delete();
        }
    }

    public static FileItem  getMultipartFile(File file, String fieldName){
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem(fieldName, "text/plain", true, file.getName());
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try(
                FileInputStream fis = new FileInputStream(file);
                OutputStream os = item.getOutputStream()
        ) {
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return item;
    }

    /**
     * 获取视频文件的播放长度(mp4、mov格式)
     * @param videoPath 本地视频路径
     * @return 单位为秒
     */
    public static long getMp4Duration(String videoPath) {
        IsoFile isoFile = null;
        try {
            isoFile = new IsoFile(videoPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return isoFile.getMovieBox().getMovieHeaderBox().getDuration() /
                isoFile.getMovieBox().getMovieHeaderBox().getTimescale();
    }

}
